"""
告警通知系统
实现邮件、短信、WebSocket等通知渠道，创建告警通知的模板和个性化配置，开发通知发送状态的跟踪和重试
"""
import asyncio
import logging
import json
import smtplib
import aiohttp
from datetime import datetime, timedelta
from typing import List, Dict, Optional, Any, Callable
from uuid import uuid4
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
import re
from collections import defaultdict, deque

from schemas.alert_management import (
    AlertEvent, NotificationTemplate, NotificationConfig, AlertNotification,
    NotificationChannel, AlertLevel, AlertCategory
)

logger = logging.getLogger(__name__)


class TemplateEngine:
    """模板引擎"""
    
    @staticmethod
    def render_template(template: str, variables: Dict[str, Any]) -> str:
        """渲染模板"""
        try:
            # 简单的变量替换
            result = template
            for key, value in variables.items():
                placeholder = f"{{{key}}}"
                result = result.replace(placeholder, str(value))
            
            # 处理条件语句 {if condition}content{/if}
            result = TemplateEngine._process_conditionals(result, variables)
            
            # 处理循环语句 {for item in items}content{/for}
            result = TemplateEngine._process_loops(result, variables)
            
            return result
        except Exception as e:
            logger.error(f"模板渲染失败: {e}")
            return template
    
    @staticmethod
    def _process_conditionals(template: str, variables: Dict[str, Any]) -> str:
        """处理条件语句"""
        pattern = r'\{if\s+(\w+)\}(.*?)\{/if\}'
        
        def replace_conditional(match):
            condition = match.group(1)
            content = match.group(2)
            
            if condition in variables and variables[condition]:
                return content
            return ""
        
        return re.sub(pattern, replace_conditional, template, flags=re.DOTALL)
    
    @staticmethod
    def _process_loops(template: str, variables: Dict[str, Any]) -> str:
        """处理循环语句"""
        pattern = r'\{for\s+(\w+)\s+in\s+(\w+)\}(.*?)\{/for\}'
        
        def replace_loop(match):
            item_var = match.group(1)
            list_var = match.group(2)
            content = match.group(3)
            
            if list_var not in variables:
                return ""
            
            items = variables[list_var]
            if not isinstance(items, list):
                return ""
            
            result = ""
            for item in items:
                item_content = content.replace(f"{{{item_var}}}", str(item))
                result += item_content
            
            return result
        
        return re.sub(pattern, replace_loop, template, flags=re.DOTALL)


class EmailNotificationChannel:
    """邮件通知渠道"""
    
    def __init__(self, smtp_host: str, smtp_port: int, username: str, password: str,
                 use_tls: bool = True):
        self.smtp_host = smtp_host
        self.smtp_port = smtp_port
        self.username = username
        self.password = password
        self.use_tls = use_tls
    
    async def send_notification(self, notification: AlertNotification) -> bool:
        """发送邮件通知"""
        try:
            # 创建邮件消息
            msg = MIMEMultipart()
            msg['From'] = self.username
            msg['To'] = notification.recipient
            msg['Subject'] = Header(notification.subject, 'utf-8')
            
            # 添加邮件内容
            body = MIMEText(notification.content, 'html', 'utf-8')
            msg.attach(body)
            
            # 发送邮件
            with smtplib.SMTP(self.smtp_host, self.smtp_port) as server:
                if self.use_tls:
                    server.starttls()
                server.login(self.username, self.password)
                server.send_message(msg)
            
            logger.info(f"邮件通知发送成功: {notification.notification_id}")
            return True
            
        except Exception as e:
            logger.error(f"邮件通知发送失败: {e}")
            return False


class SMSNotificationChannel:
    """短信通知渠道"""
    
    def __init__(self, api_url: str, api_key: str, api_secret: str):
        self.api_url = api_url
        self.api_key = api_key
        self.api_secret = api_secret
    
    async def send_notification(self, notification: AlertNotification) -> bool:
        """发送短信通知"""
        try:
            # 准备短信数据
            sms_data = {
                'api_key': self.api_key,
                'api_secret': self.api_secret,
                'phone': notification.recipient,
                'message': notification.content[:500]  # 限制短信长度
            }
            
            # 发送HTTP请求
            async with aiohttp.ClientSession() as session:
                async with session.post(self.api_url, json=sms_data) as response:
                    if response.status == 200:
                        logger.info(f"短信通知发送成功: {notification.notification_id}")
                        return True
                    else:
                        logger.error(f"短信通知发送失败: HTTP {response.status}")
                        return False
                        
        except Exception as e:
            logger.error(f"短信通知发送失败: {e}")
            return False


class WebSocketNotificationChannel:
    """WebSocket通知渠道"""
    
    def __init__(self):
        self.connections: Dict[str, Any] = {}  # 存储WebSocket连接
        self.room_connections: Dict[str, List[str]] = {}  # 房间连接映射
        self.user_rooms: Dict[str, List[str]] = {}  # 用户房间映射
    
    def add_connection(self, user_id: str, websocket):
        """添加WebSocket连接"""
        self.connections[user_id] = websocket
        logger.info(f"WebSocket连接已添加: {user_id}")
    
    def remove_connection(self, user_id: str):
        """移除WebSocket连接"""
        if user_id in self.connections:
            del self.connections[user_id]
            
            # 从房间中移除用户
            if user_id in self.user_rooms:
                for room in self.user_rooms[user_id]:
                    if room in self.room_connections and user_id in self.room_connections[room]:
                        self.room_connections[room].remove(user_id)
                del self.user_rooms[user_id]
            
            logger.info(f"WebSocket连接已移除: {user_id}")
    
    def join_room(self, user_id: str, room: str):
        """用户加入房间"""
        if room not in self.room_connections:
            self.room_connections[room] = []
        
        if user_id not in self.room_connections[room]:
            self.room_connections[room].append(user_id)
        
        if user_id not in self.user_rooms:
            self.user_rooms[user_id] = []
        
        if room not in self.user_rooms[user_id]:
            self.user_rooms[user_id].append(room)
        
        logger.info(f"用户 {user_id} 加入房间 {room}")
    
    def leave_room(self, user_id: str, room: str):
        """用户离开房间"""
        if room in self.room_connections and user_id in self.room_connections[room]:
            self.room_connections[room].remove(user_id)
        
        if user_id in self.user_rooms and room in self.user_rooms[user_id]:
            self.user_rooms[user_id].remove(room)
        
        logger.info(f"用户 {user_id} 离开房间 {room}")
    
    async def send_notification(self, notification: AlertNotification) -> bool:
        """发送WebSocket通知"""
        try:
            user_id = notification.recipient
            if user_id not in self.connections:
                logger.warning(f"用户 {user_id} 没有WebSocket连接")
                return False
            
            websocket = self.connections[user_id]
            
            # 准备通知数据
            notification_data = {
                'type': 'alert_notification',
                'notification_id': notification.notification_id,
                'alert_id': notification.alert_id,
                'subject': notification.subject,
                'content': notification.content,
                'timestamp': datetime.now().isoformat()
            }
            
            # 发送WebSocket消息
            await websocket.send_text(json.dumps(notification_data))
            
            logger.info(f"WebSocket通知发送成功: {notification.notification_id}")
            return True
            
        except Exception as e:
            logger.error(f"WebSocket通知发送失败: {e}")
            return False
    
    async def broadcast_to_room(self, room: str, message: Dict[str, Any]) -> int:
        """向房间广播消息"""
        if room not in self.room_connections:
            return 0
        
        success_count = 0
        failed_users = []
        
        for user_id in self.room_connections[room]:
            if user_id in self.connections:
                try:
                    websocket = self.connections[user_id]
                    await websocket.send_text(json.dumps(message))
                    success_count += 1
                except Exception as e:
                    logger.error(f"向用户 {user_id} 发送消息失败: {e}")
                    failed_users.append(user_id)
        
        # 清理失败的连接
        for user_id in failed_users:
            self.remove_connection(user_id)
        
        logger.info(f"房间 {room} 广播消息，成功: {success_count}, 失败: {len(failed_users)}")
        return success_count
    
    async def broadcast_real_time_alert(self, alert_data: Dict[str, Any]) -> int:
        """广播实时告警"""
        message = {
            'type': 'real_time_alert',
            'alert_data': alert_data,
            'timestamp': datetime.now().isoformat()
        }
        
        # 广播到所有监控房间
        total_sent = 0
        for room in ['monitoring', 'alerts', 'admin']:
            sent_count = await self.broadcast_to_room(room, message)
            total_sent += sent_count
        
        return total_sent


class WebhookNotificationChannel:
    """Webhook通知渠道"""
    
    def __init__(self):
        self.timeout = 30  # 请求超时时间
    
    async def send_notification(self, notification: AlertNotification) -> bool:
        """发送Webhook通知"""
        try:
            webhook_url = notification.recipient  # recipient存储webhook URL
            
            # 准备Webhook数据
            webhook_data = {
                'notification_id': notification.notification_id,
                'alert_id': notification.alert_id,
                'subject': notification.subject,
                'content': notification.content,
                'timestamp': datetime.now().isoformat()
            }
            
            # 发送HTTP请求
            async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=self.timeout)) as session:
                async with session.post(webhook_url, json=webhook_data) as response:
                    if 200 <= response.status < 300:
                        logger.info(f"Webhook通知发送成功: {notification.notification_id}")
                        return True
                    else:
                        logger.error(f"Webhook通知发送失败: HTTP {response.status}")
                        return False
                        
        except Exception as e:
            logger.error(f"Webhook通知发送失败: {e}")
            return False


class MobilePushNotificationChannel:
    """移动推送通知渠道"""
    
    def __init__(self, push_service_url: str, app_key: str, app_secret: str):
        self.push_service_url = push_service_url
        self.app_key = app_key
        self.app_secret = app_secret
    
    async def send_notification(self, notification: AlertNotification) -> bool:
        """发送移动推送通知"""
        try:
            # 准备推送数据
            push_data = {
                'app_key': self.app_key,
                'app_secret': self.app_secret,
                'device_token': notification.recipient,
                'title': notification.subject,
                'body': notification.content,
                'data': {
                    'notification_id': notification.notification_id,
                    'alert_id': notification.alert_id
                }
            }
            
            # 发送HTTP请求
            async with aiohttp.ClientSession() as session:
                async with session.post(self.push_service_url, json=push_data) as response:
                    if response.status == 200:
                        logger.info(f"移动推送通知发送成功: {notification.notification_id}")
                        return True
                    else:
                        logger.error(f"移动推送通知发送失败: HTTP {response.status}")
                        return False
                        
        except Exception as e:
            logger.error(f"移动推送通知发送失败: {e}")
            return False


class NotificationRetryManager:
    """通知重试管理器"""
    
    def __init__(self, max_retries: int = 3, retry_delays: List[int] = None):
        self.max_retries = max_retries
        self.retry_delays = retry_delays or [60, 300, 900]  # 1分钟, 5分钟, 15分钟
        self.retry_queue: deque = deque()
        self.running = False
    
    def add_failed_notification(self, notification: AlertNotification):
        """添加失败的通知到重试队列"""
        retry_item = {
            'notification': notification,
            'retry_count': notification.retry_count + 1,
            'next_retry_time': datetime.now() + timedelta(
                seconds=self.retry_delays[min(notification.retry_count, len(self.retry_delays) - 1)]
            )
        }
        self.retry_queue.append(retry_item)
    
    async def start_retry_worker(self, notification_service):
        """启动重试工作器"""
        self.running = True
        while self.running:
            try:
                await self._process_retry_queue(notification_service)
                await asyncio.sleep(30)  # 每30秒检查一次
            except Exception as e:
                logger.error(f"重试工作器错误: {e}")
                await asyncio.sleep(60)
    
    def stop_retry_worker(self):
        """停止重试工作器"""
        self.running = False
    
    async def _process_retry_queue(self, notification_service):
        """处理重试队列"""
        now = datetime.now()
        processed_items = []
        
        while self.retry_queue:
            item = self.retry_queue.popleft()
            
            if item['next_retry_time'] <= now:
                notification = item['notification']
                
                if notification.retry_count < self.max_retries:
                    # 重试发送
                    success = await notification_service._send_single_notification(notification)
                    
                    if success:
                        logger.info(f"通知重试成功: {notification.notification_id}")
                    else:
                        # 继续重试
                        notification.retry_count += 1
                        self.add_failed_notification(notification)
                else:
                    logger.error(f"通知重试次数超限: {notification.notification_id}")
            else:
                # 还没到重试时间，放回队列
                processed_items.append(item)
        
        # 将未到时间的项目放回队列
        self.retry_queue.extend(processed_items)


class AlertNotificationService:
    """告警通知服务"""
    
    def __init__(self):
        self.templates: Dict[str, NotificationTemplate] = {}
        self.configs: Dict[str, NotificationConfig] = {}
        self.channels: Dict[NotificationChannel, Any] = {}
        self.template_engine = TemplateEngine()
        self.retry_manager = NotificationRetryManager()
        
        # 通知历史记录
        self.notification_history: List[AlertNotification] = []
        self.max_history_size = 10000
        
        # 统计信息
        self.stats = {
            'notifications_sent': 0,
            'notifications_failed': 0,
            'notifications_retried': 0,
            'notifications_by_channel': defaultdict(int)
        }
    
    def configure_email_channel(self, smtp_host: str, smtp_port: int, 
                               username: str, password: str, use_tls: bool = True):
        """配置邮件通知渠道"""
        self.channels[NotificationChannel.EMAIL] = EmailNotificationChannel(
            smtp_host, smtp_port, username, password, use_tls
        )
    
    def configure_sms_channel(self, api_url: str, api_key: str, api_secret: str):
        """配置短信通知渠道"""
        self.channels[NotificationChannel.SMS] = SMSNotificationChannel(
            api_url, api_key, api_secret
        )
    
    def configure_websocket_channel(self):
        """配置WebSocket通知渠道"""
        self.channels[NotificationChannel.WEBSOCKET] = WebSocketNotificationChannel()
    
    def configure_webhook_channel(self):
        """配置Webhook通知渠道"""
        self.channels[NotificationChannel.WEBHOOK] = WebhookNotificationChannel()
    
    def configure_mobile_push_channel(self, push_service_url: str, app_key: str, app_secret: str):
        """配置移动推送通知渠道"""
        self.channels[NotificationChannel.MOBILE_PUSH] = MobilePushNotificationChannel(
            push_service_url, app_key, app_secret
        )
    
    async def add_template(self, template: NotificationTemplate):
        """添加通知模板"""
        self.templates[template.template_id] = template
        logger.info(f"添加通知模板: {template.name}")
    
    async def add_config(self, config: NotificationConfig):
        """添加通知配置"""
        self.configs[config.config_id] = config
        logger.info(f"添加通知配置: {config.name}")
    
    async def send_alert_notifications(self, alert_event: AlertEvent) -> List[AlertNotification]:
        """发送告警通知"""
        notifications = []
        
        # 查找匹配的通知配置
        matching_configs = self._find_matching_configs(alert_event)
        
        for config in matching_configs:
            if not config.enabled:
                continue
            
            # 检查时间窗口
            if not self._is_in_time_window(config):
                continue
            
            # 为每个渠道和接收者创建通知
            for channel in config.channels:
                if channel not in self.channels:
                    logger.warning(f"通知渠道未配置: {channel}")
                    continue
                
                for recipient in config.recipients:
                    notification = await self._create_notification(
                        alert_event, config, channel, recipient
                    )
                    notifications.append(notification)
        
        # 发送通知
        for notification in notifications:
            await self._send_notification(notification)
        
        return notifications
    
    def _find_matching_configs(self, alert_event: AlertEvent) -> List[NotificationConfig]:
        """查找匹配的通知配置"""
        matching_configs = []
        
        for config in self.configs.values():
            # 检查告警级别过滤
            if config.alert_levels and alert_event.level not in config.alert_levels:
                continue
            
            # 检查告警类别过滤
            if config.alert_categories and alert_event.category not in config.alert_categories:
                continue
            
            matching_configs.append(config)
        
        return matching_configs
    
    def _is_in_time_window(self, config: NotificationConfig) -> bool:
        """检查是否在时间窗口内"""
        if not config.time_windows:
            return True
        
        now = datetime.now()
        current_time = now.strftime("%H:%M")
        current_weekday = now.strftime("%A").lower()
        
        for window in config.time_windows:
            start_time = window.get('start_time')
            end_time = window.get('end_time')
            weekdays = window.get('weekdays', [])
            
            # 检查星期
            if weekdays and current_weekday not in weekdays:
                continue
            
            # 检查时间
            if start_time and end_time:
                if start_time <= current_time <= end_time:
                    return True
            else:
                return True
        
        return False
    
    async def _create_notification(self, alert_event: AlertEvent, config: NotificationConfig,
                                 channel: NotificationChannel, recipient: str) -> AlertNotification:
        """创建通知"""
        notification_id = str(uuid4())
        
        # 获取模板
        template_id = config.template_mapping.get(channel.value)
        template = self.templates.get(template_id) if template_id else None
        
        # 准备模板变量
        template_vars = {
            'alert_id': alert_event.alert_id,
            'title': alert_event.title,
            'message': alert_event.message,
            'level': alert_event.level.value,
            'category': alert_event.category.value,
            'location': alert_event.location or '未知位置',
            'camera_id': alert_event.camera_id or '',
            'classroom_id': alert_event.classroom_id or '',
            'teacher_id': alert_event.teacher_id or '',
            'created_at': alert_event.created_at.strftime("%Y-%m-%d %H:%M:%S"),
            'recipient': recipient
        }
        
        # 渲染模板
        if template:
            subject = self.template_engine.render_template(template.subject_template, template_vars)
            content = self.template_engine.render_template(template.body_template, template_vars)
        else:
            # 使用默认模板
            subject = f"告警通知: {alert_event.title}"
            content = f"告警消息: {alert_event.message}\n时间: {template_vars['created_at']}\n位置: {template_vars['location']}"
        
        return AlertNotification(
            notification_id=notification_id,
            alert_id=alert_event.alert_id,
            channel=channel,
            recipient=recipient,
            subject=subject,
            content=content
        )
    
    async def _send_notification(self, notification: AlertNotification):
        """发送通知"""
        try:
            success = await self._send_single_notification(notification)
            
            if success:
                notification.status = "sent"
                notification.sent_at = datetime.now()
                self.stats['notifications_sent'] += 1
            else:
                notification.status = "failed"
                notification.error_message = "发送失败"
                self.stats['notifications_failed'] += 1
                
                # 添加到重试队列
                self.retry_manager.add_failed_notification(notification)
            
            # 更新统计
            self.stats['notifications_by_channel'][notification.channel.value] += 1
            
            # 添加到历史记录
            self._add_to_history(notification)
            
        except Exception as e:
            logger.error(f"发送通知异常: {e}")
            notification.status = "error"
            notification.error_message = str(e)
            self.stats['notifications_failed'] += 1
    
    async def _send_single_notification(self, notification: AlertNotification) -> bool:
        """发送单个通知"""
        channel = notification.channel
        
        if channel not in self.channels:
            logger.error(f"通知渠道未配置: {channel}")
            return False
        
        channel_handler = self.channels[channel]
        return await channel_handler.send_notification(notification)
    
    def _add_to_history(self, notification: AlertNotification):
        """添加到历史记录"""
        self.notification_history.append(notification)
        
        # 限制历史记录大小
        if len(self.notification_history) > self.max_history_size:
            self.notification_history = self.notification_history[-self.max_history_size:]
    
    async def get_notification_history(self, alert_id: Optional[str] = None,
                                     channel: Optional[NotificationChannel] = None,
                                     limit: int = 100) -> List[AlertNotification]:
        """获取通知历史"""
        history = self.notification_history
        
        if alert_id:
            history = [n for n in history if n.alert_id == alert_id]
        
        if channel:
            history = [n for n in history if n.channel == channel]
        
        return history[-limit:]
    
    def get_notification_stats(self) -> Dict[str, Any]:
        """获取通知统计"""
        return {
            **self.stats,
            'total_templates': len(self.templates),
            'total_configs': len(self.configs),
            'configured_channels': list(self.channels.keys()),
            'retry_queue_size': len(self.retry_manager.retry_queue),
            'history_size': len(self.notification_history)
        }
    
    async def start_services(self):
        """启动服务"""
        # 启动重试工作器
        asyncio.create_task(self.retry_manager.start_retry_worker(self))
        logger.info("告警通知服务已启动")
    
    async def stop_services(self):
        """停止服务"""
        self.retry_manager.stop_retry_worker()
        logger.info("告警通知服务已停止")
    
    # ==================== 实时告警推送 ====================
    
    async def send_real_time_alert(self, alert_data: Dict[str, Any]) -> bool:
        """发送实时告警推送"""
        try:
            # 获取WebSocket通道
            websocket_channel = self.channels.get(NotificationChannel.WEBSOCKET)
            if not websocket_channel:
                logger.warning("WebSocket通道未配置，无法发送实时告警")
                return False
            
            # 广播实时告警
            sent_count = await websocket_channel.broadcast_real_time_alert(alert_data)
            
            # 更新统计
            self.stats['notifications_sent'] += sent_count
            self.stats['notifications_by_channel']['websocket'] += sent_count
            
            logger.info(f"实时告警推送成功，发送给 {sent_count} 个连接")
            return sent_count > 0
            
        except Exception as e:
            logger.error(f"发送实时告警失败: {e}")
            return False
    
    async def send_priority_alert(self, alert_data: Dict[str, Any], priority: str = "high") -> bool:
        """发送优先级告警"""
        try:
            # 根据优先级确定推送策略
            if priority == "critical":
                # 严重告警：所有渠道推送
                return await self._send_multi_channel_alert(alert_data, ["websocket", "email", "sms"])
            elif priority == "high":
                # 高级告警：WebSocket + 邮件
                return await self._send_multi_channel_alert(alert_data, ["websocket", "email"])
            else:
                # 普通告警：仅WebSocket
                return await self.send_real_time_alert(alert_data)
                
        except Exception as e:
            logger.error(f"发送优先级告警失败: {e}")
            return False
    
    async def _send_multi_channel_alert(self, alert_data: Dict[str, Any], channels: List[str]) -> bool:
        """多渠道发送告警"""
        success_count = 0
        
        for channel_name in channels:
            try:
                if channel_name == "websocket":
                    if await self.send_real_time_alert(alert_data):
                        success_count += 1
                elif channel_name in ["email", "sms"]:
                    # 创建临时告警事件用于发送通知
                    temp_alert = self._create_temp_alert_event(alert_data)
                    notifications = await self.send_alert_notifications(temp_alert)
                    if notifications:
                        success_count += 1
            except Exception as e:
                logger.error(f"通过 {channel_name} 发送告警失败: {e}")
        
        return success_count > 0
    
    def _create_temp_alert_event(self, alert_data: Dict[str, Any]) -> 'AlertEvent':
        """创建临时告警事件"""
        from schemas.alert_management import AlertEvent, AlertLevel, AlertCategory
        
        return AlertEvent(
            alert_id=str(uuid4()),
            title=alert_data.get('algorithm_name', '实时告警'),
            message=f"摄像头 {alert_data.get('camera_id')} 检测到异常",
            level=AlertLevel.HIGH,
            category=AlertCategory.SECURITY,
            camera_id=str(alert_data.get('camera_id', '')),
            created_at=datetime.now()
        )
    
    # ==================== WebSocket连接管理 ====================
    
    def add_websocket_connection(self, user_id: str, websocket):
        """添加WebSocket连接"""
        websocket_channel = self.channels.get(NotificationChannel.WEBSOCKET)
        if websocket_channel:
            websocket_channel.add_connection(user_id, websocket)
    
    def remove_websocket_connection(self, user_id: str):
        """移除WebSocket连接"""
        websocket_channel = self.channels.get(NotificationChannel.WEBSOCKET)
        if websocket_channel:
            websocket_channel.remove_connection(user_id)
    
    def join_monitoring_room(self, user_id: str, room: str = "monitoring"):
        """加入监控房间"""
        websocket_channel = self.channels.get(NotificationChannel.WEBSOCKET)
        if websocket_channel:
            websocket_channel.join_room(user_id, room)
    
    def leave_monitoring_room(self, user_id: str, room: str = "monitoring"):
        """离开监控房间"""
        websocket_channel = self.channels.get(NotificationChannel.WEBSOCKET)
        if websocket_channel:
            websocket_channel.leave_room(user_id, room)
    
    async def broadcast_system_message(self, message: str, room: str = "monitoring") -> int:
        """广播系统消息"""
        websocket_channel = self.channels.get(NotificationChannel.WEBSOCKET)
        if not websocket_channel:
            return 0
        
        message_data = {
            'type': 'system_message',
            'message': message,
            'timestamp': datetime.now().isoformat()
        }
        
        return await websocket_channel.broadcast_to_room(room, message_data)
    
    # ==================== 告警分级处理 ====================
    
    async def process_graded_alert(self, alert_data: Dict[str, Any]) -> bool:
        """处理分级告警"""
        try:
            # 根据告警数据确定级别
            alert_level = self._determine_alert_level(alert_data)
            
            # 根据级别处理告警
            if alert_level == "critical":
                return await self._handle_critical_alert(alert_data)
            elif alert_level == "high":
                return await self._handle_high_alert(alert_data)
            elif alert_level == "medium":
                return await self._handle_medium_alert(alert_data)
            else:
                return await self._handle_low_alert(alert_data)
                
        except Exception as e:
            logger.error(f"处理分级告警失败: {e}")
            return False
    
    def _determine_alert_level(self, alert_data: Dict[str, Any]) -> str:
        """确定告警级别"""
        algorithm_name = alert_data.get('algorithm_name', '')
        confidence = alert_data.get('confidence', 0)
        result_data = alert_data.get('result_data', {})
        
        # 基于算法类型和置信度确定级别
        if algorithm_name in ['conflict_detection', 'behavior_analysis']:
            behavior_type = result_data.get('behavior_type', '').lower()
            if behavior_type in ['fighting', 'violence', 'emergency']:
                return "critical"
            elif behavior_type in ['running', 'crowding', 'intrusion']:
                return "high"
            else:
                return "medium"
        
        elif algorithm_name == 'crowd_density':
            density = result_data.get('density', 0)
            person_count = result_data.get('person_count', 0)
            if density > 0.9 or person_count > 30:
                return "critical"
            elif density > 0.7 or person_count > 20:
                return "high"
            else:
                return "medium"
        
        elif algorithm_name == 'waste_detection':
            waste_count = result_data.get('waste_count', 0)
            if waste_count > 10:
                return "high"
            elif waste_count > 5:
                return "medium"
            else:
                return "low"
        
        # 默认基于置信度
        if confidence > 0.9:
            return "high"
        elif confidence > 0.7:
            return "medium"
        else:
            return "low"
    
    async def _handle_critical_alert(self, alert_data: Dict[str, Any]) -> bool:
        """处理严重告警"""
        # 立即推送 + 多渠道通知 + 自动升级
        success = await self.send_priority_alert(alert_data, "critical")
        
        # 记录严重告警
        logger.critical(f"严重告警: 摄像头 {alert_data.get('camera_id')}, 算法 {alert_data.get('algorithm_name')}")
        
        return success
    
    async def _handle_high_alert(self, alert_data: Dict[str, Any]) -> bool:
        """处理高级告警"""
        return await self.send_priority_alert(alert_data, "high")
    
    async def _handle_medium_alert(self, alert_data: Dict[str, Any]) -> bool:
        """处理中级告警"""
        return await self.send_real_time_alert(alert_data)
    
    async def _handle_low_alert(self, alert_data: Dict[str, Any]) -> bool:
        """处理低级告警"""
        # 低级告警只记录，不推送
        logger.info(f"低级告警: 摄像头 {alert_data.get('camera_id')}, 算法 {alert_data.get('algorithm_name')}")
        return True